#include <string.h>
#include "esp8266.h"
#include "./BSP/bsp_usart.h"
#include "timer_delays.h"
#include "./BSP/bsp_usart.h"

//宏定义使能和复位引脚的输出
#define RstPin PBout(9)
#define EnPin PBout(8)

//初始化ESP8266的结构体
static ESP8266_ResTypeDef res = {
    .RCC_APB2Periph_GPIOxEN = RCC_APB2Periph_GPIOB,
    .RCC_APB2Periph_GPIOxRST = RCC_APB2Periph_GPIOB,
    .GPIOxEN = GPIOB,
    .GPIOxRST = GPIOB,
    .en_pin = GPIO_Pin_8,
    .rst_pin = GPIO_Pin_9,
    .comx = COM3,
    .baudrate = 115200
};

static void _config_pin(uint32_t RCC_APB2Periph_GPIOx, GPIO_TypeDef *GPIOx, uint16_t pin)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx, ENABLE);

    GPIO_InitTypeDef    GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = pin;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOx, &GPIO_InitStruct); 
}


#define _config_rst_pin(clk, gpio, pin) _config_pin(clk, gpio, pin)
#define _config_en_pin(clk, gpio, pin) _config_pin(clk, gpio, pin)
#define _config_usart(comx, baud) SerialPortInit(comx, baud)

/*
º¯Êý¹¦ÄÜ£º³õÊ¼»¯ESP8266µÄ¹¤×÷×´Ì¬
*/
void ESP8266_Init(void)
{
    // ÅäÖÃÊ¹ÄÜÒý½Å
    _config_en_pin(res.RCC_APB2Periph_GPIOxEN, res.GPIOxEN, res.en_pin);
    EnPin = 1;    // ¸ßµçÆ½ÓÐÐ§
    
    // ÅäÖÃ¸´Î»Òý½Å
    _config_rst_pin(res.RCC_APB2Periph_GPIOxRST, res.GPIOxRST, res.rst_pin);
    RstPin = 0;     // µÍµçÆ½ÓÐÐ§
    DelayMS(200);
    RstPin = 1;     // ÉÏµç¸´Î»Ò»´Î

    // ÅäÖÃ´®¿ÚÍ¨ÐÅ¿Ú
    _config_usart(res.comx, res.baudrate);
    
}

static char esp8266_recv_buf[2048];

static UsartRecvMsgType esp8266_msg = {
    .finish = 0,
    .index = 0,
    .buf = esp8266_recv_buf,
    .buf_size = 2048
};

/*
º¯Êý¹¦ÄÜ£º´Ó´®¿ÚusartµÄ½ÓÊÕ¼Ä´æÆ÷¶ÁÈ¡×Ö½Ú£¬²¢»º³åµ½Ò»¿éÄÚ´æÖÐ
*/
void ESP8266_RecStr(u8 c)
{  
    if (esp8266_msg.index < esp8266_msg.buf_size - 1)
        esp8266_msg.buf[esp8266_msg.index++] = c;
}

void ESP8266_SetFlag(void)
{
    esp8266_msg.finish = 1;
}

u8 ESP8266_GetMsg(void)
{
    if (esp8266_msg.finish) {
        printf("%s", esp8266_msg.buf);
        esp8266_msg.index = 0;
    }
    return 1;
}

/*
º¯Êý¹¦ÄÜ£ºÏòESP8266·¢ËÍÖ¸ÁîÇëÇó£¬²¢½âÎöÆä»ØÓ¦
*/
bool ESP8266_SendCMD(const char *cmd, const char *replay1, const char *replay2, u16 dly)
{
    bool ret = false;
    u16 i;
    
    esp8266_msg.index = 0;         // Çå¿Õ½ÓÊÕ»º³åÇø
    memset(esp8266_msg.buf, 0, esp8266_msg.buf_size); // Ê±¼äÏûºÄ
    
    usart_send_msg(res.comx, cmd); // ·¢ËÍATÖ¸Áî
    
    for (i = 0;i < dly; i++) { // µÈ´ýÒ»¶ÎÊ±¼ä£¬²¢²é¿´»ØÓ¦
        DelayMS(100);
        
        if (replay1 != NULL && strstr(esp8266_msg.buf, replay1) != NULL) {
            ret = true;
            break;
        }
        
        if (replay1 != NULL && strstr(esp8266_msg.buf, replay2) != NULL) {
            ret = true;
            break;
        }
        printf("-");
        //if (strstr(esp8266_msg.buf, "busy") != NULL)
            //i--;
    }
    
    if (replay1 == NULL && replay2 == NULL)
        ret = true;
    
    printf("\r\n[ESP]response: |%s|,cost:%u ms$@\r\n", esp8266_msg.buf, i * 100);
    
    return ret;
}

/*
º¯Êý¹¦ÄÜ£º²âÊÔMCUÓëESP8266µÄÍ¨ÐÅ¹¦ÄÜ
*/
bool ESP8266_ConnTest(void)
{
    return ESP8266_SendCMD("AT\r\n", "OK", NULL, 10);
}
#if 0 // ²âÊÔ½Ó¿Ú
bool ESP8266_ATTest(void)
{
    //char buf[128] = {'\0'};
    
    // ·¢ËÍATÖ¸Áî
    printf("Send to esp8266\r\n");
    esp8266_msg.index = 0;
    usart_send_msg(COM3, "AT\r\n"); // ·¢ËÍATÖ¸Áî
    
    DelayMS(200);
    
    // ½ÓÊÕÏìÓ¦OK
    if (esp8266_msg.index > 0) {
        esp8266_msg.buf[esp8266_msg.index] = '\0';
        printf("index:%d, Response: %s\r\n", esp8266_msg.index, esp8266_msg.buf);
        
    }
    
    return true;
}
#endif

/*
º¯Êý¹¦ÄÜ£ºÄ£Ê½ÅäÖÃ
*/
bool ESP8266_ModeCfg(ENUM_NetModeTypeDef mode)
{
    char cmd[16] = {'\0'};
    sprintf(cmd, "AT+CWMODE=%u\r\n", mode + 1);
    return ESP8266_SendCMD(cmd, "OK", NULL, 100);
}

/*
º¯Êý¹¦ÄÜ£ºÄ£Ê½ÅäÖÃ
*/
bool ESP8266_JoinAP(const char *ssid, const char *pwd)
{
    char cmd[64] = {'\0'};
    sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"\r\n", ssid, pwd);
    return ESP8266_SendCMD(cmd, "OK", NULL, 100);
}

static char protocal_str[2][5] = {"TCP", "UDP"};

/*
º¯Êý¹¦ÄÜ£ºÁ¬½Ó·þÎñÆ÷
*/
bool ESP8266_Connect(ENUM_NetProTypeDef pro, const char *server_ip, u16 port)
{
    char cmd[128] = {'\0'};
    //printf("ESP8266_Connect+++\r\n");
    sprintf(cmd, "AT+CIPSTART=\"%s\",\"%s\",%u\r\n", protocal_str[pro], server_ip, port);
    //printf("pack:%s", cmd);
    return ESP8266_SendCMD(cmd, "OK", NULL, 100);
}

/*
 * º¯ÊýÃû£ºESP8266_UnvarnishSend
 * ÃèÊö  £ºÅäÖÃWF-ESP8266Ä£¿é½øÈëÍ¸´«·¢ËÍ
 * ÊäÈë  £ºÎÞ
 * ·µ»Ø  : 1£¬ÅäÖÃ³É¹¦
 *         0£¬ÅäÖÃÊ§°Ü
 * µ÷ÓÃ  £º±»Íâ²¿µ÷ÓÃ
 */
bool ESP8266_UnvarnishSend ( void )
{
	if ( ! ESP8266_SendCMD("AT+CIPMODE=1\r\n", "OK", 0, 50))
		return false;
	
	return ESP8266_SendCMD ("AT+CIPSEND\r\n", "OK", ">", 50);
}


/*
 * º¯ÊýÃû£ºESP8266_ExitUnvarnishSend
 * ÃèÊö  £ºÅäÖÃWF-ESP8266Ä£¿éÍË³öÍ¸´«Ä£Ê½
 * ÊäÈë  £ºÎÞ
 * ·µ»Ø  : ÎÞ
 * µ÷ÓÃ  £º±»Íâ²¿µ÷ÓÃ
 */
void ESP8266_ExitUnvarnishSend ( void )
{
	DelayMS(1000);
	usart_send_msg(res.comx, "+++");
	DelayMS(500); 
	
}

/*
º¯Êý¹¦ÄÜ£ºESP8266½¨Á¢TCPÁ¬½Ó
*/

bool ESP8266_BuildTCPConn(const char *ssid, const char *passwd, const char *sip, u16 port)
{
    //printf("\r\n+++ip:%s,%u\r\n", sip, port);
    // AT ²âÊÔ
    while(!ESP8266_ConnTest());
    
    // AT + CWMODE
    //ESP8266_ModeCfg(STA);
    
    // AT + CWLAP(²»×ö)
    // AT+CWJAP
    ESP8266_JoinAP(ssid, passwd);
    
    // AT+CIPSTART=
    //printf("ip:%s,%u\r\n", sip, port);
    ESP8266_Connect(enumTCP, sip, port);
    
    // ÅäÖÃÎªÍ¸´«Ä£Ê½
    ESP8266_UnvarnishSend();
    
    return true;
}

/*
º¯Êý¹¦ÄÜ£ºESP8266µÄTCP·¢ËÍº¯Êý
²ÎÊý£º
enumEnUnvarnishTx£¬Ö¸¶¨ÊÇ·ñÊ¹ÓÃÍ¸´«Ä£Ê½
*/
u16 ESP8266_SendString(FunctionalState enumEnUnvarnishTx, const char *str)
{
    
    u16 len = strlen(str);
    
    if ( enumEnUnvarnishTx ) {
		usart_send_msg(res.comx, str);
		return len;
	}

    bool ret;
    char cmd[32] = {'\0'};
    sprintf(cmd, "AT+CIPSEND=%u\r\n", len);
    ret = ESP8266_SendCMD(cmd, "> ", NULL, 100);
    if (!ret)
        return 0;
    
    usart_send_msg(res.comx, str);
    return len;
}
/*
º¯Êý¹¦ÄÜ£ºESP8266µÄTCP½ÓÊÕº¯Êý
*/


